package dungeonTools;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import java.util.Random;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

/**
 * @author Tom Jacobs & Ewoud De Moor
 * @version 3.0
 */
public class CoordinateTest {

	public static Coordinate basis;
	public static Coordinate twoThreeFive;
	@Before
	public void setUp() throws Exception {
		basis = new Coordinate(0,0,0);
		twoThreeFive = new Coordinate(2, 3, 5);
	}

	@After
	public void tearDown() throws Exception {
	}

	@Test
	public void testHashCode() {
		assertEquals(1763348891,basis.hashCode());
	}

	@Test(expected = IllegalArgumentException.class)
	public void constructorFail_X() {
		new Coordinate(-1,0,0);
	}

	@Test(expected = IllegalArgumentException.class)
	public void constructorFail_Y() {
		new Coordinate(0,-2,0);
	}

	@Test(expected = IllegalArgumentException.class)
	public void constructorFail_Z() {
		new Coordinate(0,0,-10);
	}

	@Test(expected = IllegalArgumentException.class)
	public void constructorFail_ALL() {
		new Coordinate(-1,-2,-10);
	}

	@Test
	public void getCoordinates() {
		assertEquals(2, twoThreeFive.getxCoordinate());
		assertEquals(3, twoThreeFive.getyCoordinate());
		assertEquals(5, twoThreeFive.getzCoordinate());
	}


	@Test
	public void testEquals() {
		assertTrue(basis.equals(new Coordinate(0,0,0)));
	}

	@Test
	public void testNotEquals() {
		assertFalse(basis.equals(twoThreeFive));
	}

	@Test
	public void differentHashCodes(){
		assertFalse(basis.hashCode() == twoThreeFive.hashCode());
	}

	@Test
	public void testToString() {
		assertEquals("(2,3,5)",twoThreeFive.toString());
	}

	@Test
	public void hashChangesOverArguments(){
		assertTrue(basis.hashCode() == (new Coordinate(0, 0, 0).hashCode()));
		assertFalse(basis.hashCode() == (new Coordinate(0, 0, 1).hashCode()));
		assertFalse(basis.hashCode() == (new Coordinate(0, 1, 0).hashCode()));
		assertFalse(basis.hashCode() == (new Coordinate(0, 1, 1).hashCode()));
		assertFalse(basis.hashCode() == (new Coordinate(1, 0, 0).hashCode()));
		assertFalse(basis.hashCode() == (new Coordinate(1, 0, 1).hashCode()));
		assertFalse(basis.hashCode() == (new Coordinate(1, 1, 0).hashCode()));
		assertFalse(basis.hashCode() == (new Coordinate(1, 1, 1).hashCode()));
		assertFalse((new Coordinate(1, 0, 1).hashCode()) == (new Coordinate(1, 0, 0).hashCode()));
		assertTrue((new Coordinate(1, 0, 1).hashCode()) == (new Coordinate(1, 0, (int)1.99).hashCode()));
		assertFalse((new Coordinate(1, 0, 1).hashCode()) == (new Coordinate(1, 0, 2).hashCode()));
	}

	/*
	 * Statistische test, faalt soms (wegens randomness).
	 * Normaal is er geen probleem mee.
	 */
	@Test
	public void hashcodeChiSquareTest(){//met 95% significantie
		Random rand = new Random();
		int[] frequencyArray = new int[16];
		for(int i = 0; i < 16000; i++){
			Coordinate coordinate = new Coordinate(rand.nextInt(255),rand.nextInt(255),rand.nextInt(255));
			int hash = coordinate.hashCode();
			frequencyArray[ (int)(Math.abs(hash-1)/0x07ffffff) ]++;
		}
		double chiSquare = 0;
		for(int i = 0; i < 16; i++){
			chiSquare += Math.pow((frequencyArray[i] - 1000),2)/1000;	
		}
		System.out.println("Chi-Square value: " + chiSquare);
		assertTrue(chiSquare < 18.49);
	}


}
